package scenetracer.core;

import scenetracer.math.Matrix4;
import scenetracer.math.OrthoNormalBasis;
import scenetracer.math.Point3;
import scenetracer.math.Vector3;

public class Camera {
	
	private Point3 eye;
	private Point3 target;
	private Vector3 up;
	private double fov;
	private double aspect;
	private Matrix4 cameraToWorld;
	float au;
	float av;
		
	public Point3 getEye() {
		return eye;
	}

	public void setEye(Point3 eye) {
		this.eye = eye;
	}

	public Point3 getTarget() {
		return target;
	}

	public void setTarget(Point3 target) {
		this.target = target;
	}

	public Vector3 getUp() {
		return up;
	}

	public void setUp(Vector3 up) {
		this.up = up;		
	}

	public double getFov() {
		return fov;
	}

	public void setFov(double fov) {
		this.fov = fov;
	}

	public double getAspect() {
		return aspect;
	}

	public void setAspect(double aspect) {
		this.aspect = aspect;
	}
	
	public void update(){
		cameraToWorld = Matrix4.fromBasis(OrthoNormalBasis.makeFromWV(Point3.sub(eye, target, new Vector3()), up));
		cameraToWorld = Matrix4.translation(eye.x, eye.y, eye.z).multiply(cameraToWorld);
		
		au = (float) Math.tan(Math.toRadians(fov * 0.5f));
		//av = au / (float)aspect;
		av = au / (float)aspect;
	}
	
	public Ray getRay(float x, float y, int width, int height){

//		 float du = ((2.0f * x - width) / (float)width ) * (float)Math.tan(au);
//	     float dv = ((2.0f * y  - height) / (float)height)* (float)Math.tan(av);
		 float du = -au + ((2.0f * au * x) / (width - 1.0f));
	     float dv = -av + ((2.0f * av * y) / (height - 1.0f));		

	     Vector3 dir = new Vector3(du, dv, -1);
	     dir.normalize();
	     Ray ray = new Ray(new Point3(0, 0 ,0), dir);
	     
	     ray.transform(cameraToWorld);
	     ray.getDirection().normalize();	     
	     return ray;
	}
	
}
